Skip to content

Conversation

@chaptersix
Copy link
Owner

Summary

This PR addresses all feedback from @bergundy on main PR temporalio#877:

Key Changes Made:

  • Moved Dockerfile to repo root - Changed from .github/docker/cli.Dockerfile to Dockerfile
  • Simplified Docker build - Removed complex multi-stage build, now uses Alpine directly instead of scratch
  • Removed parameterization - No more ARG ALPINE_IMAGE, uses fixed Alpine version
  • Better user handling - Changed USER 1000:1000 to USER temporal:temporal for readability
  • Deleted Makefile - Removed as it's not needed in this repo
  • Updated GitHub Actions - Use major version tags instead of fixed hashes
  • Converted bash to JavaScript - Registry configuration logic now uses GitHub Script
  • Kept fork support - Maintained auto-detection between docker.io (temporalio) and ghcr.io (forks)

Testing:

  • ✅ Docker build works correctly with simplified Dockerfile
  • ✅ Docker bake integration works with updated configuration
  • ✅ All workflow file references updated properly

Files Changed:

  • Dockerfile (new) - Simplified single-stage Alpine build
  • .github/docker/docker-bake.hcl - Updated Dockerfile path and removed ALPINE_IMAGE
  • .github/workflows/build-and-publish.yml - Updated to major version tags
  • .github/workflows/update-latest-tag.yml - Converted bash to JavaScript
  • Makefile (deleted) - Removed as not needed

This addresses all reviewer feedback while maintaining the core functionality of automating Docker image builds and publishing.

Major improvements:
- Add full parameterization (registry, namespace, image name)
- Auto-detect registry: temporalio → docker.io, others → ghcr.io
- Separate workflow for managing 'latest' tag on release events
- Dynamic Docker labels using GITHUB_REPOSITORY variable
- Add packages:write permission for GHCR
- Remove artifact uploading (no longer needed)

Benefits:
- Works out-of-box for both upstream and forks
- Flexible registry support (Docker Hub, GHCR, any registry)
- Clean separation of release vs latest-tag concerns
- Proper package association in GitHub

Configuration requirements:
- DOCKER_USERNAME and DOCKER_PASSWORD secrets needed for Docker Hub
- GITHUB_TOKEN automatically provides GHCR access
- Move Dockerfile to repo root and simplify to single-stage Alpine build
- Remove complex multi-stage build and ARG ALPINE_IMAGE parameterization
- Change USER 1000:1000 to USER temporal:temporal for readability
- Delete Makefile entirely (not needed in this repo)
- Update GitHub Actions to use major version tags instead of fixed hashes
- Convert bash registry logic to JavaScript in update-latest-tag.yml
- Keep fork support logic for temporalio vs ghcr.io auto-detection
- Update docker-bake.hcl to reference new Dockerfile location
- Test Docker build functionality - all working correctly
- Replace bash script with GitHub Script for registry configuration
- Keep all existing functionality including fork support logic
- Improve maintainability and consistency with update-latest-tag.yml
- Use environment variables to pass inputs to JavaScript script
- Replace Alpine base with gcr.io/distroless/static-debian12:nonroot
- Use multi-stage build to copy CA certificates from temporary Alpine stage
- Remove user creation since distroless images handle non-root execution
- Improve security and reduce image size with distroless approach
- Maintain same functionality while following security best practices
- Move docker-bake.hcl from .github/docker/ to repo root
- Update workflow references to use new file location
- Remove old cli.Dockerfile from .github/docker/ directory
- Consolidate Docker build files in root directory for better organization
- Maintain all existing functionality with cleaner file structure
- Replace gcr.io/distroless/static-debian12:nonroot with FROM scratch
- Create completely minimal image with only essential components
- Manually copy CA certificates, passwd, and group files from Alpine stage
- Maintain non-root user execution with USER 1000:1000
- Achieve smallest possible attack surface and image size
- Follow container security best practices with truly minimal base
- Use ARG TARGETARCH (built-in Docker Buildx arg) instead of custom BUILDARCH
- Copy binaries from GoReleaser output structure: dist/nix_linux_amd64_v1/temporal
- Add multi-stage dist build to properly handle GoReleaser output paths
- Remove unnecessary TARGETPLATFORM from workflows and docker-bake.hcl
- Ensure Docker build works correctly with actual GoReleaser binary locations
- Remove empty .github/docker directory since all files moved to root
- dist/ already exists in .gitignore (no changes needed)
- Consolidate all Docker build files in root directory
- Final clean structure: Dockerfile, docker-bake.hcl in repo root
- Add step to detect if release is marked as latest (not prerelease/draft)
- Use GitHub API to check release status via github-script
- Set TAG_LATEST based on actual release latest status
- Push both version tag and latest tag when appropriate
- Maintains existing version tagging behavior for non-latest releases
- Works for both temporalio (docker.io) and fork (ghcr.io) registries
- Correct TAG_LATEST logic to use boolean comparison == 'true'
- When release is latest: push both 'latest' AND 'vX.Y.Z' tags
- When release is not latest: push only 'vX.Y.Z' tag (no latest)
- Ensures users can always pull :latest for stable releases
- Maintains version-specific tags for all releases
The intermediate stage approach copies both architecture binaries into
normalized paths within Docker's build context, then uses TARGETARCH
to select the correct one. This is more reliable than filesystem
wildcards which depend on the host build environment.
Remove the intermediate dist stage and copy binaries directly using
TARGETARCH-based wildcards. The Alpine base (digest-pinned to 3.22)
provides CA certificates and a non-root user environment in a simple,
maintainable format.
- Remove syntax directive comment
- Remove leading ./ from COPY path for consistency
- ARG TARGETARCH declared after FROM (required for build stage scope)
- Verified working with goreleaser output structure
The intermediate stage approach is more reliable than wildcards as it:
- Operates entirely within Docker's build context
- Explicitly copies both architecture binaries to normalized paths
- Allows clean selection via TARGETARCH without filesystem assumptions
- Avoids reliance on shell glob expansion behavior
@chaptersix chaptersix merged commit 84c2380 into main Nov 22, 2025
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants